package pers.chao.cacheable.core.factory;

import org.springframework.stereotype.Component;
import pers.chao.cacheable.core.*;
import pers.chao.cacheable.core.annotation.*;
import pers.chao.cacheable.core.consts.RedisStructEnum;
import pers.chao.cacheable.infrastructure.ErrorDesc;
import pers.chao.cacheable.core.CacheableException;
import pers.chao.tool.aspect.AopUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Description: redis缓存操作类实例化工厂
 *
 * @author W.Chao
 * @date 2020/10/2 0:56
 **/
@Component
public class CacheProcessorFactoryImpl implements ICacheProcessorFactory {
	private Map<RedisStructEnum, Class> strategyMap;

	public CacheProcessorFactoryImpl() {
		strategyMap = new HashMap<>();
		// 根据类型存储，方便获取
		strategyMap.put(RedisStructEnum.BITMAP, CacheBitmap.class);
		strategyMap.put(RedisStructEnum.LIST, CacheList.class);
		strategyMap.put(RedisStructEnum.MAP, CacheMap.class);
		strategyMap.put(RedisStructEnum.SET, CacheSet.class);
		strategyMap.put(RedisStructEnum.STRING, CacheValue.class);
		strategyMap.put(RedisStructEnum.ZSET, CacheZSet.class);
	}

	@Override
	public <T extends Annotation> AbstractCacheProcessor get(Method method, Annotation cacheStructAnno) {
		RedisStruct structAnno = AopUtil.findAnnotatedAnnotation(method,cacheStructAnno.annotationType(),RedisStruct.class);
		RedisStructEnum struct = structAnno.value();
		// 获取设置好的redis类型处理器
		Class structClass = strategyMap.get(struct);
		AbstractCacheProcessor cacheOperation = getByRealType(method, struct, structClass);
		if (cacheOperation == null){
			throw new CacheableException(ErrorDesc.CACHE_PROCESSOR_FACTORY_ERROR, method, struct, struct);
		}
		return cacheOperation;
	}

	/**
	 * 根据类型转换
	 *
	 * @param method
	 * @param type
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("all")
	private AbstractCacheProcessor getByRealType(Method method, RedisStructEnum type, Class clazz){
		switch (type) {
			case BITMAP:
				CacheBitmap bitmap = (CacheBitmap) method.getAnnotation(clazz);
				return new CacheBitmapProcessor(bitmap);
			case LIST:
				CacheList list = (CacheList) method.getAnnotation(clazz);
				return new CacheListProcessor(list);
			case MAP:
				CacheMap map = (CacheMap) method.getAnnotation(clazz);
				return new CacheMapProcessor(map);
			case SET:
				CacheSet set = (CacheSet) method.getAnnotation(clazz);
				return new CacheSetProcessor(set);
			case STRING:
				CacheValue string = (CacheValue) method.getAnnotation(clazz);
				return new CacheValueProcessor(string);
			case ZSET:
				CacheZSet zset = (CacheZSet) method.getAnnotation(clazz);
				return new CacheZSetProcessor(zset);
			default:
				return null;
		}
	}

}
